#ifndef ALARM_CLOCK_H_
#define ALARM_CLOCK_H_

/* INCLUDES *******************************************************************/

#include <stdbool.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "ses_button.h"
#include "ses_lcd.h"
#include "ses_led.h"
#include "ses_timer.h"
#include "ses_scheduler.h"
#include "ses_buzzer.h"



/* MACROS AND DEFINES *********************************************************/

#define ALARM_ON			1
#define ALARM_OFF			0
#define DAY					24
#define HOUR				60
#define ALARM_TIMEOUT		30000

/** Signals of the FSM */
enum Signal {
	INIT, ROTARY, JOYSTICK, SYSTEM_TIME_MATCHES, NONE
};



/* TYPES AND STRUCTS **********************************************************/

typedef struct Event Event;
typedef struct Fsm   Fsm;

typedef void (*State)(Fsm*, const Event*);

struct Fsm {
	State    state; 	// the current state
	uint8_t  alarmSet;  // is alarm enabled ?
	uint32_t timeSet;  	// temporary buffer for time
};

typedef struct type_timeRTC {
	uint8_t  hour;
	uint8_t  minute;
	uint8_t  second;
	uint16_t milli;
} type_timeRTC;

struct Event {
	uint8_t  signal; 	// multi purpose signal
};



/* FSM STATES *****************************************************************/

/**
 * Initial state of the FSM.
 */
void alarmClock_init(Fsm* me, State init);

/**
 * Set-up mode: changing the hour of alarm or time.
 */
void alarmClock_set_hours(Fsm *me, const Event *e);

/**
 * Set-up mode: changing the minute of alarm or time.
 */
void alarmClock_set_minutes(Fsm *me, const Event *e);

/**
 * Normal mode: alarm set to off.
 */
void alarmClock_alarm_off(Fsm *me, const Event *e);

/**
 * Normal mode: alarm set to on.
 */
void alarmClock_alarm_on(Fsm *me, const Event *e);

/**
 * Alarm mode: alarm is buzzing.
 */
void alarmClock_buzzing(Fsm *me, const Event *e);



/* FSM FUCNTIONS **************************************************************/

/**
 * Sets and calls the initial state of the FSM.
 */
inline static void fsm_init(Fsm* me, State init);

/**
 * Dispatches events to state machine, called every 1 ms.
 */
inline static void fsm_dispatch(Fsm* me, const Event* event);

/**
 * Execute the dispatch function from the scheduler.
 */
void fsm_dispatching();



/* HELPER FUNCTIONS ***********************************************************/

/**
 * Periodically display the current clock each second.
 */
void display_clock();

/**
 * Checks if alarm time equals current time of clock.
 */
void match_alarm_clock();

/**
 * Change the current signal, called asynchronously by the buttons.
 *
 * @param signal	Signal enum
 */
void set_event_signal(uint8_t signal);

/**
 * Switch off the alarm.
 */
void set_alarm_off();

/**
 * Periodically switch the buzz on and off.
 */
void toggle_buzz();

/**
 * Periodically toggle the green LED.
 */
void toggle_green_led();

/**
 * Calculates amount of milliseconds from type_timeRTC object.
 *
 * @param time	type_timeRTC object with hours and minutes
 * @return corresponding time in milliseconds
 */
uint32_t calculate_miliseconds(const type_timeRTC *time);



#endif /* ALARM_CLOCK_H_ */
